package internal

import (
	"bytes"
	"reflect"
	"time"
	"unicode/utf8"
	"unsafe"
)

// Zero 返回指定Any类型的零值
func Zero[T any]() T {
	var zero T
	return zero
}

// IsZero 判断对象是否为零值
//   - 约定为零值:  nil, 为nil的任何指针
//   - 约定为非零值:  struct{}, 不为nil的指针, 不可比较类型
func IsZero(v any) bool {
	if v == nil {
		return true
	}
	// 尝试先通过断言检查基本类型的零值
	switch vs := v.(type) {
	case string:
		return vs == ""
	case bool:
		return !vs
	case int:
		return vs == 0
	case int8:
		return vs == 0
	case int16:
		return vs == 0
	case int32: // rune
		return vs == 0
	case int64:
		return vs == 0
	case uint:
		return vs == 0
	case uint8: // byte
		return vs == 0
	case uint16:
		return vs == 0
	case uint32:
		return vs == 0
	case uint64:
		return vs == 0
	case uintptr:
		return vs == 0
	case float32:
		return vs == 0
	case float64:
		return vs == 0
	case complex64:
		return vs == 0
	case complex128:
		return vs == 0
	case error:
		return vs == nil
	case struct{}:
		return false
	case time.Time:
		return vs.IsZero()
	case time.Duration:
		return vs == 0
	case time.Month:
		return vs == 0
	case time.Weekday:
		return vs == 0
	case *string:
		return vs == nil
	case *bool:
		return vs == nil
	case *int:
		return vs == nil
	case *int8:
		return vs == nil
	case *int16:
		return vs == nil
	case *int32:
		return vs == nil
	case *int64:
		return vs == nil
	case *uint:
		return vs == nil
	case *uint8:
		return vs == nil
	case *uint16:
		return vs == nil
	case *uint32:
		return vs == nil
	case *uint64:
		return vs == nil
	case *uintptr:
		return vs == nil
	case *float32:
		return vs == nil
	case *float64:
		return vs == nil
	case *complex64:
		return vs == nil
	case *complex128:
		return vs == nil
	case *error:
		return vs == nil
	case *struct{}:
		return vs == nil
	case *time.Time:
		return vs == nil
	case *time.Duration:
		return vs == nil
	case *time.Month:
		return vs == nil
	case *time.Weekday:
		return vs == nil
	case []string:
		return vs == nil
	case []bool:
		return vs == nil
	case []int:
		return vs == nil
	case []int8:
		return vs == nil
	case []int16:
		return vs == nil
	case []int32: // []rune
		return vs == nil
	case []int64:
		return vs == nil
	case []uint:
		return vs == nil
	case []uint8: // []byte
		return vs == nil
	case []uint16:
		return vs == nil
	case []uint32:
		return vs == nil
	case []uint64:
		return vs == nil
	case []uintptr:
		return vs == nil
	case []float32:
		return vs == nil
	case []float64:
		return vs == nil
	case []complex64:
		return vs == nil
	case []complex128:
		return vs == nil
	case []time.Time:
		return vs == nil
	case []time.Duration:
		return vs == nil
	case []time.Month:
		return vs == nil
	case []time.Weekday:
		return vs == nil
	case map[string]any:
		return vs == nil
	case map[string]string:
		return vs == nil
	case map[string]int:
		return vs == nil
	case map[int]any:
		return vs == nil
	case map[int]string:
		return vs == nil
	case map[int]int:
		return vs == nil
	}
	rv := reflect.ValueOf(v)
	// reflect func (v Value) IsZero() bool
	switch rv.Kind() {
	case
		reflect.Chan, reflect.Func,
		reflect.Interface, reflect.Map,
		reflect.Pointer, reflect.Slice, reflect.UnsafePointer:
		// Chan, Func, Interface, Map, Pointer(Ptr), Slice, UnsafePointer
		return rv.IsNil()
	case reflect.String, reflect.Bool,
		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
		reflect.Float32, reflect.Float64,
		reflect.Complex64, reflect.Complex128,
		reflect.Array, reflect.Struct:
		return rv.IsZero()
	default:
		rt := rv.Type()
		if !rt.Comparable() {
			return false
		}
		return v == reflect.Zero(rt).Interface()
	}
}

// IsNil 判断 any 对象是否为 nil
func IsNil(v any) bool {
	if v == nil {
		return true
	}
	value := reflect.ValueOf(v)
	switch value.Kind() {
	case
		reflect.Chan, reflect.Func,
		reflect.Interface, reflect.Map,
		reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
		return value.IsNil()
	}
	return false
}

// IsEmpty 判断 any 对象是否为空
//   - 空值检查：如果输入值为 nil或nil 指针，函数返回 true。
//   - 指针处理：如果值是指针类型，函数会递归地解引用指针，直到找到非指针类型或遇到 nil 指针。
//   - 集合类型：对于数组、映射、切片和字符串，函数检查其长度是否为零。
//   - 基本类型：对于布尔值、整数、浮点数、接口和指针，函数使用 reflect.Value 的 IsZero 方法来判断其是否为空。
//   - 默认情况：对于未明确处理的其他类型，函数返回 false。
func IsEmpty(v any) bool {
	if v == nil {
		return true
	}
	// 尝试先通过断言检查基本类型的零值
	switch vs := v.(type) {
	case string:
		return vs == ""
	case bool:
		return !vs
	case int:
		return vs == 0
	case int8:
		return vs == 0
	case int16:
		return vs == 0
	case int32:
		return vs == 0
	case int64:
		return vs == 0
	case uint:
		return vs == 0
	case uint8:
		return vs == 0
	case uint16:
		return vs == 0
	case uint32:
		return vs == 0
	case uint64:
		return vs == 0
	case uintptr:
		return vs == 0
	case float32:
		return vs == 0
	case float64:
		return vs == 0
	case complex64:
		return vs == 0
	case complex128:
		return vs == 0
	case error:
		return vs == nil
	case struct{}:
		return false
	case time.Time:
		return vs.IsZero()
	case time.Duration:
		return vs == 0
	case time.Month:
		return vs == 0
	case time.Weekday:
		return vs == 0
	case *string:
		return vs == nil
	case *bool:
		return vs == nil || !(*vs)
	case *int:
		return vs == nil || *vs == 0
	case *int8:
		return vs == nil || *vs == 0
	case *int16:
		return vs == nil || *vs == 0
	case *int32:
		return vs == nil || *vs == 0
	case *int64:
		return vs == nil || *vs == 0
	case *uint:
		return vs == nil || *vs == 0
	case *uint8:
		return vs == nil || *vs == 0
	case *uint16:
		return vs == nil || *vs == 0
	case *uint32:
		return vs == nil || *vs == 0
	case *uint64:
		return vs == nil || *vs == 0
	case *uintptr:
		return vs == nil || *vs == 0
	case *float32:
		return vs == nil || *vs == 0
	case *float64:
		return vs == nil || *vs == 0
	case *complex64:
		return vs == nil || *vs == 0
	case *complex128:
		return vs == nil || *vs == 0
	case *error:
		return vs == nil || *vs == nil
	case *struct{}:
		return vs == nil
	case *time.Time:
		return vs == nil || (*vs).IsZero()
	case *time.Duration:
		return vs == nil || *vs == 0
	case *time.Month:
		return vs == nil || *vs == 0
	case *time.Weekday:
		return vs == nil || *vs == 0
	}
	rv := reflect.ValueOf(v)
	for rv.Kind() == reflect.Ptr {
		if rv.IsNil() {
			return true
		}
		rv = rv.Elem()
	}
	switch rv.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return rv.Len() == 0
	case reflect.Bool,
		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
		reflect.Float32, reflect.Float64,
		reflect.Interface, reflect.Pointer:
		return rv.IsZero()
	}
	return false
}

// UnderefVal 探测 any 目标, 将指针类型脱敏为原始标量类型
//   - 如果目标是nil, 则返回nil
//   - 如果目标非指针, 则返回原值
//   - 如果目标含有方法, 则返回原值
//   - 如果目标是nil指针, 则返回nil
//   - 如果目标是非nil指针, 则返回指针指向的指向的值(any类型的原始标量)
func UnderefVal(v any) any {
	if v == nil {
		return nil
	}
	val := reflect.ValueOf(v)
	if !val.IsValid() || val.Kind() != reflect.Ptr {
		return v
	}
	if val.NumMethod() > 0 {
		return v
	}
	// 脱敏指针类型, 直到非指针为止
	seen := make(map[uintptr]struct{})
	for val.Kind() == reflect.Ptr {
		if val.IsNil() {
			return nil
		}
		// 防止循环引用
		if val.CanAddr() {
			addr := val.UnsafeAddr()
			if _, exists := seen[addr]; exists {
				return nil
			}
			seen[addr] = struct{}{}
		}
		val = val.Elem()
	}
	switch val.Kind() {
	// reflect.Pointer, // Pointer == Ptr
	case reflect.Chan, reflect.Func, reflect.Map, reflect.UnsafePointer,
		reflect.Interface, reflect.Slice:
		if val.IsNil() {
			return nil
		}
	}
	if !val.IsValid() || !val.CanInterface() {
		return nil
	}
	return val.Interface()
}

// StringToBytes 字符串转Bytes切片
//   - 在go版本<1.20中, 通过unsafe包和reflect包实现，其主要原理是拿到底层数组的指针，然后转换成[]byte或string。
//   - 在go版本>=1.20中 由于安全性问题reflect包中的StringHeader和SliceHeader已被标注为deprecated，建议使用unsafe包来实现转换。
//   - Use unsafe.String or unsafe.StringData instead.
//   - Use unsafe.Slice or unsafe.SliceData instead.
func StringToBytes(data string) []byte {
	size := len(data)
	if size == 0 {
		return []byte{}
	}
	return unsafe.Slice(unsafe.StringData(data), size)
}

// BytesToString Bytes切片转字符串
func BytesToString(data []byte) string {
	size := len(data)
	if size == 0 {
		return ""
	}
	return unsafe.String(unsafe.SliceData(data), size)
}

// StringToRunes 字符串转rune切片
func StringToRunes(str string) []rune {
	size := utf8.RuneCountInString(str)
	if size == 0 {
		return []rune{}
	}
	// 按字符rune遍历字符串
	var buf = make([]rune, 0, size)
	for _, r := range str {
		buf = append(buf, r)
	}
	return buf
}

// RunesToString Runes切片转字符串
func RunesToString(data []rune) string {
	size := len(data)
	if size == 0 {
		return ""
	}
	var buf bytes.Buffer
	for i := range size {
		buf.WriteRune(data[i])
	}
	return buf.String()
}

// RunesToBytes Runes切片转Bytes切片
func RunesToBytes(data []rune) []byte {
	size := len(data)
	if size == 0 {
		return []byte{}
	}
	var buf bytes.Buffer
	for i := range size {
		buf.WriteRune(data[i])
	}
	return buf.Bytes()
}

// OneRuneToBytes Rune转String
func OneRuneToString(r rune) string {
	if r <= 255 {
		return string(byte(r))
	}
	buf := make([]byte, 4)
	n := utf8.EncodeRune(buf, r)
	return string(buf[:n])
}

// OneRuneToBytes Rune转Bytes切片
func OneRuneToBytes(r rune) []byte {
	if r <= 255 {
		return []byte{byte(r)}
	}
	buf := make([]byte, 4)
	n := utf8.EncodeRune(buf, r)
	return buf[:n]
}

// BytesToRunes Bytes切片转Runes切片
func BytesToRunes(data []byte) []rune {
	size := utf8.RuneCount(data)
	if size == 0 {
		return []rune{}
	}
	var buf = make([]rune, 0, size)
	for len(data) > 0 {
		r, size := utf8.DecodeRune(data)
		buf = append(buf, r)
		data = data[size:]
	}
	return buf
}
